
export class RoleHelper {

    // 移动到目标
    static moveToTarget(creep: Creep, target: RoomObject, color = 'ffffff') {
        if (creep.pos.isNearTo(target)) {
            return true;
        }

        creep.moveTo(target, { visualizePathStyle: { stroke: color } });
        return false;
    }

    // 可储能建筑
    private static canStoreEnergy(structure: Structure): structure is StructureStorage | StructureContainer | StructureTerminal {
        const type = structure.structureType;
        return (type === STRUCTURE_STORAGE || type === STRUCTURE_CONTAINER || type === STRUCTURE_TERMINAL);
    }

    // 可接收能源建筑
    static canReceiveEnergy(structure: Structure): structure is StructureSpawn | StructureExtension | StructureTower {
        const type = structure.structureType;
        return (type === STRUCTURE_SPAWN || type === STRUCTURE_EXTENSION || type === STRUCTURE_TOWER);
    }

    // 获取能源矿
    static findEnergySource(creep: Creep): Source {
        const sources = creep.room.find(FIND_SOURCES);

        if (sources.length > 0) {
            return creep.pos.findClosestByPath(sources);
        }

        return null;
    }

    // 采源
    private static harvestEnergySource(creep: Creep, target: Source): boolean {
        if (target) {
            const result = creep.harvest(target);
            if (result === ERR_NOT_IN_RANGE) {
                this.moveToTarget(creep, target, '#ffaa00');
                creep.say('⛏️采源中');
                return true;
            } else if (result === OK) {
                creep.say('⛏️采源');
                return true;
            }
        }
        return false;
    }

    // 采集
    static harvestEnergy(creep: Creep): boolean {
        var target = this.findEnergySource(creep);
        return this.harvestEnergySource(creep, target);
    }

    // 找到丢掉的能源
    private static findDroppedEnergy(creep: Creep, minEnergy: number): Resource | null {
        const droppedEnergy = creep.pos.findClosestByPath(FIND_DROPPED_RESOURCES, {
            filter: r => r.resourceType === RESOURCE_ENERGY && r.amount >= minEnergy
        });
        if (droppedEnergy) return droppedEnergy;
    }

    // 拾取丢掉的能源
    private static pickEnergy(creep: Creep, target: Resource): boolean {
        if (target) {
            const result = creep.pickup(target);
            if (result === ERR_NOT_IN_RANGE) {
                this.moveToTarget(creep, target, '#ffaa00');
                creep.say('📦拾取中');
                return true;
            } else if (result === OK) {
                creep.say('📦拾取');
                return true;
            }
        }

        return false;
    }

    // 拾取能源
    static pickupEnergy(creep: Creep): boolean {
        const target = this.findDroppedEnergy(creep, 100);
        return this.pickEnergy(creep, target);
    }

    // 找到附近可以储能的建筑
    static findStoreStructure(creep: Creep, minEnergy: number): StructureContainer | StructureStorage | StructureTerminal | StructureSpawn | null {
        const storageTypes: StructureConstant[] = [
            STRUCTURE_STORAGE,
            STRUCTURE_TERMINAL,
            STRUCTURE_CONTAINER,
        ];

        for (const type of storageTypes) {
            const storage =
                creep.pos.findClosestByPath(FIND_STRUCTURES, {
                    filter: s =>
                        s.structureType === type &&
                        //this.canStoreEnergy(s) &&
                        'store' in s &&
                        s.store.getUsedCapacity(RESOURCE_ENERGY) > minEnergy
                }) as StructureContainer | StructureStorage | StructureTerminal | StructureSpawn | null;
            if (storage) return storage;
        }

        creep.say('没找到储能建筑');
    }

    // 取能源
    static withdrawEnergy(creep: Creep, target: StructureContainer | StructureStorage | StructureTerminal | StructureSpawn) {
        if (target) {
            const result = creep.withdraw(target, RESOURCE_ENERGY);
            if (result === ERR_NOT_IN_RANGE) {
                this.moveToTarget(creep, target, '#ffaa00');
                creep.say('🏦取能中');
                return true;
            } else if (result === OK) {
                creep.say('🏦取能');
                return true;
            }
        }

        return false

    }

    // 取能
    static getStoreEnergy(creep: Creep): boolean {
        const target = this.findStoreStructure(creep, 100);
        return this.withdrawEnergy(creep, target);
    }

    // 找到修建目标
    private static findBuildTarget(creep: Creep): any | null {
        const buildTarget = creep.pos.findClosestByPath(FIND_MY_CONSTRUCTION_SITES);
        return buildTarget;
    }

    // 修建目标
    private static buildTarget(creep: Creep, target: any): boolean {
        if (target) {
            const result = creep.build(target);
            if (result === ERR_NOT_IN_RANGE) {
                RoleHelper.moveToTarget(creep, target, '#ff7700');
                creep.say('🏗️去工地');
                return true;
            } else if (result === OK) {
                creep.say('🔧建设中');
                return true;
            }
        }

        return false;
    }

    // 修建
    static build(creep: Creep): boolean {
        const target = this.findBuildTarget(creep);
        return this.buildTarget(creep, target);
    }

    // 寻找储能结构
    private static findEnergySink(creep: Creep, StructureTypes?: StructureConstant[]): AnyStructure | null {
        const types = StructureTypes || [STRUCTURE_EXTENSION, STRUCTURE_SPAWN, STRUCTURE_TOWER, STRUCTURE_LAB, STRUCTURE_NUKER, STRUCTURE_POWER_SPAWN];
        const structures = creep.room.find(FIND_STRUCTURES, { filter: s => types.includes(s.structureType) && 'store' in s && (s as AnyStoreStructure).store.getFreeCapacity(RESOURCE_ENERGY) > 0 });

        if (structures.length > 0) {
            return creep.pos.findClosestByPath(structures);
        }

        return null;
    }

    // 储能
    private static transferEnergy(creep: Creep, target: AnyStructure): boolean {
        // 实现能量输送逻辑
        if (target) {
            const result = creep.transfer(target, RESOURCE_ENERGY);
            if (result === ERR_NOT_IN_RANGE) {
                this.moveToTarget(creep, target, '#00ff00');
                creep.say('⚡储能中');
                return true;
            } else if (result === OK) {
                creep.say('⚡储能');
                return true;
            }
        }

        return false;
    }

    // 储能
    static deliverEnergy(creep: Creep): boolean {
        var target = this.findEnergySink(creep);
        return this.transferEnergy(creep, target);
    }
}
